import React, {RefObject} from "react";
import {Button as AntdButton, Form as AntdForm, Form, Popconfirm, Row as AntdRow, Spin} from 'antd';
import {DeleteOutlined, PlusOutlined} from '@ant-design/icons';
import {renderItems, VJsonComponent, VJsonComponentBase,} from "../../factory";
import _ from 'lodash'
import {YvanEvent} from "../../types";
import {ColProps} from "antd/lib/grid/col";
import {Rule} from "rc-field-form/lib/interface";
import {FormInstance} from "antd/lib/form/hooks/useForm";
import {IReactionDisposer, reaction} from 'mobx'
import {apply, createViewId, YvanEventDispatch} from "../../utils/helper"

export interface RepeatVJsonProp {

    /**
     * 标题
     */
    label?: string

    /**
     * 绑定实体
     */
    bind?: string

    /**
     * 校验规则
     */
    rules: Rule[]

    /**
     * 标签跨度
     */
    labelCol?: ColProps

    /**
     * 组件跨度
     */
    wrapperCol?: ColProps

    /**
     * 关联的表单实体
     */
    formRef?: RefObject<FormInstance>

    /**
     * 是否可见
     */
    visible?: boolean

    /**
     * 校验最少个数
     */
    atleast?: 0

    colon?: boolean

    loading?: boolean

    allowRemove?: boolean
    allowInsert?: boolean

    width?: number | string

    confirmDelete?: YvanEvent<Repeat>

    /**
     * 内容元素
     */
    items: any[]
}

export interface RepeatState extends RepeatVJsonProp {

}

@VJsonComponent({
    view: 'repeat'
})
export default class Repeat extends VJsonComponentBase<RepeatVJsonProp, RepeatState> {
    static defaultProps: RepeatState = {
        loading: false,
        visible: true,
        items: [],
        rules: []
    }

    formItemName: string
    onAppendChild?: YvanEvent<Repeat>
    onRemoveChild?: YvanEvent<Repeat>
    onConfirmDelete?: YvanEvent<Repeat>
    reactionDisposer!: IReactionDisposer

    constructor(props: any) {
        super(props);

        this.onAppendChild = props.vjson.onAppendChild
        this.onRemoveChild = props.vjson.onRemoveChild
        this.onConfirmDelete = props.vjson.onConfirmDelete

        this.formItemName = props.vjson.bind ? props.vjson.bind :
            props.$default.$parentBind + '.' + props.vjson.bindChild

        if (!this.formItemName) {
            this.formItemName = _.uniqueId('name_')
        }

        _.defaults(
            props.vjson,
            props.$default,
            Repeat.defaultProps
        )
    }

    componentDidMount() {
        super.componentDidMount();

        this.reactionDisposer = reaction(
            () => {
                const datas: any[] = _.get(this.props.$context.scopeInstance, this.formItemName)
                return datas.length
            },
            length => {
                this.forceUpdate()
            }
        );
    }

    componentWillUnmount() {
        super.componentWillUnmount();
        this.reactionDisposer()
    }

    get loading(): undefined | boolean {
        return this.props.vjson.loading
    }

    set loading(v) {
        this.props.vjson.loading = v
    }

    insertRow(idx: any) {
        if (!this.formItemName) {
            console.error('请设置 repeat 组件的 bind 属性')
            return
        }
        const scope = this.props.$context.scopeInstance
        const target: any[] = _.get(scope, this.formItemName)

        if (_.isArray(target)) {
            target.splice(idx + 1, 0, {})

        } else {
            // 一个元素都没有，或不是数组元素
            _.set(scope, this.formItemName, [{}])
        }
    }

    deleteRow(idx: any) {
        if (!this.formItemName) {
            console.error('请设置 repeat 组件的 bind 属性')
            return
        }
        const scope = this.props.$context.scopeInstance
        const target: any[] = _.get(scope, this.formItemName)

        if (_.isArray(target)) {
            target.splice(idx, 1)

        } else {
            // 一个元素都没有，或不是数组元素
            _.set(scope, this.formItemName, [{}])
        }
    }

    renderData() {
        const data = _.get(this.props.$context.scopeInstance, this.formItemName)
        const key = createViewId('repeat_item')

        if (!data || !_.isArray(data) || data.length <= 0) {
            return (
                // <AntdButton onClick={() => this.insertRow.call(this, 0)}>插入</AntdButton>
                <Form.Item key={key} id={key} aria-roledescription={'button'}>
                    <AntdButton
                        type="dashed"
                        onClick={() => {
                            this.insertRow.call(this, 0);
                        }}
                        block
                    >
                        <PlusOutlined/> 添加
                    </AntdButton>
                </Form.Item>
            )
        } else {
            return _.map(data, (row, idx) => {
                return (
                    <AntdRow key={_.uniqueId('r_')}>
                        {
                            ...renderItems(this, this.props.vjson.items, {
                                $parentBind: this.formItemName + '[' + idx + ']',
                                $repeatRef: this
                            })
                        }
                        <AntdButton type="link"
                                    key={_.uniqueId('r_')}
                                    onClick={() => this.insertRow.call(this, idx)}
                                    icon={<PlusOutlined/>}/>

                        {(typeof this.props.vjson.atleast === "undefined" || idx >= this.props.vjson.atleast) ?
                            (
                                (this.onConfirmDelete) ?
                                    <Popconfirm
                                        key={_.uniqueId('r_')}
                                        title={YvanEventDispatch(this.onConfirmDelete, this, data) || "确认删除?"}
                                        onConfirm={() => this.deleteRow.call(this, idx)}
                                        okText="确定"
                                        cancelText="取消"
                                    >
                                        <AntdButton type="link" icon={<DeleteOutlined/>}
                                                    danger/>
                                    </Popconfirm> :
                                    <AntdButton type="link" danger
                                                key={_.uniqueId('r_')}
                                                onClick={() => this.deleteRow.call(this, idx)}
                                                icon={<DeleteOutlined/>}/>
                            ) : null
                        }
                    </AntdRow>
                )
            })
        }
    }

    render() {
        if (!this.formItemName) {
            throw new TypeError('请设置 repeat 组件的 bind 属性')
        }

        if (!this.props.vjson.visible) {
            return null
        }

        return (
            <Form.Item
                key={this.key} id={this.key} aria-roledescription={this.view}
                colon={apply(this, this.props.vjson.colon)}
                style={{width: this.props.vjson.width}}
                // @ts-ignore
                labelCol={this.props.vjson.labelCol}
                wrapperCol={this.props.vjson.wrapperCol}
                // name={this.formItemName}
                label={apply(this, this.props.vjson.label)}
                rules={apply(this, this.props.vjson.rules)}
            >
                {
                    this.renderData()
                }
                <Spin spinning={this.props.vjson.loading}>
                </Spin>
            </Form.Item>
        )
    }
}
